/*
 *  This project is mainly focused on developing more and more utilisties
 *  like mail utilities, dao utilities, ldap utilities, file utilities, 
 *  file importing utilities etc. for easy coding in java.
 *  
 *  Copyright (C) 2012  R.Satheesh Kumar alias GURU
 *  
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *  
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *  
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.jsmart.util.core;

import org.jsmart.util.RowMapper;

/**
 * This class acts as the base class for utilities, This class supports
 * the callback and filter classes that will be used by other utility
 * classes for performing the business logic and filtering constraints.
 * 
 * @author R.Satheesh Kumar alias GURU {pulsarcoder@gmail.com}
 * @see AbstractCallback
 * @see AbstractFilter
 * @see AbstractItemCallback
 * @see AbstractItemFilter
 * @see UtilsException
 */
public abstract class AbstractUtils {
    /**
     * This method is used as the base method for all the utilities that injecting the value of
     * the required object
     * @param <T>
     * @param <S>
     * @param s
     * @param callback
     * @param filter
     * @return
     * @throws UtilsException 
     */
    public static <T, S> T execute(S s, AbstractCallback<T, S> callback,
            AbstractFilter<S> filter) throws UtilsException {
        Utils.notNull(s, s.getClass()+" must not be null");
        Utils.notNull(callback, "AbstractDataCallback must not be null");
        Utils.notNull(filter, "AbstractDataFilter must not be null");
        if(filter.matches(s))
            return callback.doInCallback(s);
        return null;
    }
    
    /**
     * This method is used to perform the business logic for the object list.
     * This method delegates the performing of business logic code to
     * <code>execute(s, callback, filter)</code>, but the difference is that
     * this does not filters the object with the constraints for checking whether
     * the object is allowed to process with the business logic code that is
     * injected.
     * @param <T>
     * @param <S>
     * @param s
     * @param callback
     * @return
     * @throws UtilsException 
     */
    public static <S, T> T execute(S s, AbstractCallback<T, S> callback) throws UtilsException {
        return execute(s, callback, new SimpleAbstractFilter<S>());
    }

    /**
     * This method is used for executing the object affected with
     * the business logic code and also filters the object that
     * matches the filter constraints.
     * This method delegates the action to <code>execute(s, callback, filter)</code>
     * @param <S>
     * @param <T>
     * @param <U>
     * @param <V>
     * @param s
     * @param caller
     * @param filter
     * @return
     * @throws UtilsException
     */
    public static <S, T, U, V> T execute(final S s, AbstractQueryCaller<S, T, U, V> caller,
            AbstractFilter<S> filter) throws UtilsException {
        return execute(s, (AbstractCallback<T, S>)caller, filter);
    }

    /**
     * This method delegates to <code>execute(s, caller, filter)</code>, but the difference
     * is this method does not filters the object which matching the constraints
     * instead allows the object to get affected with the business
     * logic.
     * @param <S>
     * @param <T>
     * @param <U>
     * @param <V>
     * @param s
     * @param caller
     * @return
     * @throws UtilsException
     */
    public static <S, T, U, V> T execute(final S s, AbstractQueryCaller<S, T, U, V> caller)
            throws UtilsException {
        return execute(s, caller, new SimpleAbstractFilter<S>());
    }

    /**
     * This method is used to retrieve the AbstractItemCallback object from the
     * RowMapper object with SimpleAbstractItemCallback class
     * @param <U>
     * @param <V>
     * @param rowMapper
     * @return
     */
    public static <U, V> AbstractItemCallback<U, V> getSimpleItemCallback(RowMapper<U, V> rowMapper) {
        return new SimpleAbstractItemCallback<U, V>(rowMapper);
    }
    
    /**
     * This class is used for simple filter that processes all the data objects.
     * @param <T>
     * @param <V> 
     */
    public static class SimpleAbstractFilter<S> implements AbstractFilter<S> {
        public boolean matches(S s) {
            return true;
        }
    }
    
    /**
     * This class is a simple callback that does not perform any logical code
     * with the data of list.
     * @param <U>
     * @param <V> 
     */
    public static class SimpleAbstractItemCallback<U, V> implements AbstractItemCallback<U, V> {
        RowMapper<U, V> rowMapper;
        public SimpleAbstractItemCallback(RowMapper<U, V> rowMapper) {
            this.rowMapper = rowMapper;
        }
        public U doInItem(V v, Integer rowNumber) throws UtilsException {
            return rowMapper.mapRows(v);
        }
    }
    /**
     * This class is used for simple filter that processes all the data.
     * @param <T>
     * @param <S> 
     */
    public static class SimpleAbstractItemFilter<V> implements AbstractItemFilter<V> {
        public boolean matches(V v, Integer rowNumber) {
            return true;
        }
    }
}
